#include <iostream>

using std::cout;
using std::endl;

template <typename T>
class RAII
{
public:
    //在构造函数中初始化资源
    RAII(T *pdata)
    : _pdata(pdata)
    {
        cout << "RAII(T *)" << endl;
    }

    //在析构函数中释放资源
    //认为资源是new出来的
    ~RAII()
    {
        cout << "~RAII()" << endl;
        if(_pdata)
        {
            delete _pdata;
            _pdata = nullptr;
        }
    }

    //提供若访问资源的方法
    T *operator->()
    {
        return _pdata;
    }

    T &operator*()
    {
        return *_pdata;
    }

    T *get() const
    {
        return _pdata;
    }

    void reset(T *pdata)
    {
        if(_pdata)
        {
            delete _pdata;
            _pdata = nullptr;
        }

        _pdata = pdata;
    }

    //一般不允许复制或者赋值
    RAII(const RAII &rhs) = delete;
    RAII &operator=(const RAII &rhs) = delete;
private:
    /* int *_pdata; */
    /* char *_pdata; */
    /* double *_pdata; */
    T *_pdata;
};

class Point
{
public:
    Point(int ix = 0, int iy = 0)
    : _ix(ix)
    , _iy(iy)
    {
        cout << "Point(int = 0, int = 0)" << endl;
    }

    void print() const
    {
        cout << "(" << _ix 
             << ", " << _iy
             << ")" << endl;
    }

    ~Point()
    {
        cout << "~Point()" << endl;
    }
private:
    int _ix;
    int _iy;
};

void test()
{
    /* RAII<int> pInt(new int(10));//pInt的生命周期达到的时候 */

    //利用pt这个栈对象的生命周期管理了堆空间资源，然后当pt的
    //生命周期达到的时候，会执行pt的析构函数，也就是RAII的
    //析构函数，回收托管的资源,堆空间资源
    RAII<Point> pt(new Point(1, 2));//pt是栈对象
    pt->print();//pt可以像指针一样进行使用
    (*pt).print();//pt看成是一种智能指针

    cout << endl <<"====指行reset====" <<endl;
    pt.reset(new Point(4, 5));
    pt->print();

}

int main(int argc, char *argv[])
{
    test();
    return 0;
}

